package com.cn.chaomeng.utils;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import javax.net.ssl.SSLContext;
import java.security.cert.X509Certificate;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.security.cert.CertificateException;
import java.util.*;

/**
 * Created by Administrator on 2017/9/27.
 */
public class HttpUtils
{

    private static Logger log = Logger.getLogger(HttpUtils.class);

    /**
     *
     * 方法用途: 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序），并且生成url参数串<br>
     * 实现步骤: <br>
     *
     * @param paraMap   要排序的Map对象
     * @param urlEncode   是否需要URLENCODE
     * @param keyToLower    是否需要将Key转换为全小写
     *            true:key转化成小写，false:不转化
     * @return
     */
    public static String formatUrlMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower)
    {
        String buff = "";
        Map<String, String> tmpMap = paraMap;
        try
        {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(tmpMap.entrySet());
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序）
            Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>()
            {

                @Override
                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2)
                {
                    return (o1.getKey()).toString().compareTo(o2.getKey());
                }
            });
            // 构造URL 键值对的格式
            StringBuilder buf = new StringBuilder();
            for (Map.Entry<String, String> item : infoIds)
            {
                if (StringUtils.isNotBlank(item.getKey()))
                {
                    String key = item.getKey();
                    String val = item.getValue();
                    if (urlEncode)
                    {
                        val = URLEncoder.encode(val, "utf-8");
                    }
                    if (keyToLower)
                    {
                        buf.append(key.toLowerCase() + "=" + val);
                    } else
                    {
                        buf.append(key + "=" + val);
                    }
                    buf.append("&");
                }

            }
            buff = buf.toString();
            if (buff.isEmpty() == false)
            {
                buff = buff.substring(0, buff.length() - 1);
            }
        } catch (Exception e)
        {
            e.printStackTrace();
            return null;
        }
        return buff;
    }

    /**
     * 发起GET请求
     *
     * @param url 请求url
     * @return json字符串, 错误信息或者请求结果, 示例: "{"data":{}}", "{"error":{}}"
     * @throws IOException
     * @throws URISyntaxException
     */
    private static String get(String url) throws URISyntaxException, IOException {
        // 校验url是否合法
        URI target = new URI(url);
        if (!target.isAbsolute() || URIUtils.extractHost(target) == null) {
            return "{\"error\":{\"code\":404,\"message\":\"指定url不合法\"}}";
        }

        // 创建get请求
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet get = new HttpGet(url);

        return HttpUtils.getResult(httpClient, url, get);
    }


    /**
     * 发起普通POST请求
     *
     * @param url    请求url
     * @param params 请求参数
     * @return json字符串, 错误信息或者请求结果, 示例: "{"data":{}}", "{"error":{}}"
     * @throws IOException
     * @throws URISyntaxException
     */
    public static String post(String url, Map<String, String> params) throws IOException, URISyntaxException {
        // 校验url是否合法
        URI target = new URI(url);
        if (!target.isAbsolute() || URIUtils.extractHost(target) == null) {
            return "{\"error\":{\"code\":404,\"message\":\"指定url不合法\"}}";
        }

        // 创建post请求
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost post = new HttpPost(url);

        // 添加请求体参数
        if (params != null) {
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            for (Map.Entry<String, String> entry : params.entrySet()) {
                nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            post.setEntity(new UrlEncodedFormEntity(nvps, "utf8"));
        }

        return HttpUtils.getResult(httpClient, url, post);
    }


    /**
     * 发起请求,返回响应的json串
     *
     * @param httpClient HttpClient
     * @param url        请求的url
     * @param method     请求方式,包括GET和POST
     * @return json字符串, 错误信息或者请求结果, 示例: "{"data":{}}", "{"error":{}}"
     * @throws IOException
     */
    private static String getResult(CloseableHttpClient httpClient, String url,
        HttpRequestBase method) throws IOException {
        CloseableHttpResponse response = null;
        String result = null;

        try {
            // 接收response
            response = httpClient.execute(method);

            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                return "{\"error\":{\"code\":" + statusCode + ",\"message\":\"请求失败\"}}";
            }

            // 获取返回体
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(response.getEntity());

            // 释放资源
            EntityUtils.consume(entity);
        } catch (IOException ioe) {
            throw new IOException("IOException in request. Request Url:" + url, ioe);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error("Response close failed. Request Url:" + url, e);
                }
            }
        }
        return result;
    }

    public static void main(String[] args){
        String orderId = UUID.randomUUID().toString().replaceAll("-","");
        Map<String,String> postMap = new HashMap<String,String>();
        postMap.put("price","0.01");
        postMap.put("openid","ohTKdwMfltJC5Gx8gKuXxi8JgfgU");
        postMap.put("pay_title","测试测试");
        postMap.put("order_id",orderId);
        postMap.put("type","1");


        try
        {
            log.info(post("https://b.yifanpay.com/pay/hjpay",postMap));
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
